#include "engine.h"

#include "libtcod.hpp"

#include "input.h"
#include "items.h"
#include "mapcontroller.h"
#include "maps.h"
#include "messagecontroller.h"
#include "monster.h"
#include "player.h"
#include "view.h"

#include <boost/serialization/map.hpp>

using namespace fortress;
Engine::Engine()
{
	pc=0;
	gameMaps = new mapController();
	gameView = new view();
	monsterAI = new monster();
	messageController & messages = messageController::getInstance();
	messages.setView(gameView);
	input = new inputController();
	input->getMapping("keys.txt");
	//tempMap->loadFile("map1.txt");
}

Engine::Engine(std::ifstream & file)
{
	pc=0;
	gameMaps = new mapController();
	gameView = new view();
	monsterAI = new monster();
	messageController & messages = messageController::getInstance();
	messages.setView(gameView);
	input = new inputController();
	input->getMapping("keys.txt");
}

Engine::~Engine()
{
	delete input;
	delete gameView;
	delete monsterAI;
	if (itemInfo)
	{
		std::map<int,items*>::iterator it;
		
		for(it=itemInfo->begin(); it!=itemInfo->end(); it++)
		{
			delete it->second;
		}
		itemInfo->clear();
		delete itemInfo;
	}
	delete gameMaps;
	_CrtDumpMemoryLeaks();
}
void Engine::createWindow(int x, int y, std::string *title, bool fullscreen)
{
	//TCODConsole::setCustomFont("courier12x12_aa_tc.png",TCOD_FONT_LAYOUT_TCOD | TCOD_FONT_TYPE_GREYSCALE);
	TCODConsole::setCustomFont("microsoftTerminal.png",TCOD_FONT_LAYOUT_ASCII_INROW | TCOD_FONT_TYPE_GREYSCALE);
	
	TCODConsole::initRoot(x,y,title->c_str(),fullscreen);
	TCODConsole::flush();
}

void Engine::createPlayer()
{
	// insert this into the character controller
	player *newPlayer = new player(5,5,5,5,5,5, gameView);
	input->setControlled(newPlayer);
	newPlayer->setGlyph('@');
	newPlayer->setColor(TCODColor(220,220,220));
	gameMaps->getMap(0).putCharacter(newPlayer);
	map * tempMap = &gameMaps->getMap(0);
	newPlayer->setMap(tempMap);
	gameView->setMap(tempMap);
	int x,y;
	tempMap->getUpstair(x,y);
	newPlayer->setCoords(x,y);
	pc = newPlayer;
	pc->explore();
}

void Engine::loadPlayer()
{
	input->setControlled(pc);
	gameMaps->loadData();
	//gameMaps->getMap(0).putCharacter(pc);
	//pc->setMap(&gameMaps->getMap(0));
//	int x,y;
//	gameMaps->getMap(0).getUpstair(x,y);
//	pc->setCoords(x,y);
	pc->setView(gameView);
}

//eventReceiver & Engine::getEventHandler()
//{
//	static Engine instance;
//	return instance;
//}

void Engine::setWindowTitle(std::string *title)
{
	TCODConsole::setWindowTitle(title->c_str());
}

bool Engine::isGameOver()
{
	return (TCODConsole::isWindowClosed() || !input->isRunning() || pc->isDead());
}

void Engine::endGame()
{
	if (input->doSave())
	{
		std::ofstream outFile("asdf.txt");
		boost::archive::text_oarchive oa(outFile);
		oa << *this;
	}
}

bool Engine::waitForInput()
{
	return input->waitForInput() || !input->isRunning();
}

void Engine::redraw()
{
	gameView->draw();
}

void Engine::updateWorld(bool playerTurn)
{
	gameView->clearMessage();
	if (playerTurn)
	{
		// do stuff
		monsterAI->setMap(pc->currentMap);
		monsterAI->takeTurn(pc);
	}
	pc->currentMap->endTurn();
	pc->explore();
	messageController & messages = messageController::getInstance();
	while (messages.displayMessages())
	{
		// do some input thing
		input->waitForKeypress();
	}
	gameView->draw();
}

void Engine::createWorld()
{
	itemFactory makeItems;
	itemInfo = makeItems.readFile("items.txt");

	std::map<int, items*>::iterator it = itemInfo->find(0);
	int x,y;
	portal * tempPortal=gameMaps->firstMap();
	map & tempMap = gameMaps->getMap(0);	// hacky
	x=tempPortal->x;
	y=tempPortal->y;
	x++;
	for (int i=0; i<50; i++)
	{
		items * tempItem = new items(*((itemInfo->find(0))->second));
		tempItem->setCoords(x,y);
		tempMap.dropItem(*tempItem);
	}

	character * newMonster = new character(5,5,5,5,5,5,1);
	newMonster->setGlyph('f');
	newMonster->setColor(TCODColor(200,200,200));
	gameMaps->getMap(0).putCharacter(newMonster);
	monsterAI->insert(newMonster);
	y++;
	newMonster->setCoords(x,y);
}
template<class Archive>
void Engine::serialize(Archive & ar, const unsigned int version)
{
//	ar.register_type(static_cast<monster *>(NULL));

	ar & monsterAI;
	ar & pc;
	ar & gameMaps;
	ar & itemInfo;
}

void saveGame(const Engine & game, const char * filename)
{
	std::ofstream output(filename);
	boost::archive::text_oarchive oa(output);
	oa << game;
}

template void Engine::serialize<boost::archive::text_iarchive>(boost::archive::text_iarchive & ar, const unsigned int version);
